package ctm.javacode;

import java.io.* ;
import java.sql.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Date;

import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;


import org.apache.catalina.User;
import org.w3c.dom.*;
import org.xml.sax.SAXException;



@WebServlet("/menulist.do")

public class menulist extends HttpServlet {
	
	private final String SUCCESS_VIEW = "menudemo.jsp"; 
	private final String ERROR_VIEW = "commonError.jsp";  
	String nextpage = SUCCESS_VIEW ;
	String name = "";
	String sex = "";
	String work = "";
	String activity = "";
	String pressure = "";
	
	double height = 0.0 ;
	double weight = 0.0 ;
	double year = 0.0;
	
	double calofday = 0.0 ;
	
	double prot = 0.0; // 蛋白質克數
	double fat = 0.0; // 脂肪克數
	double cho = 0.0; // 醣類克數
	double proportion_prot = 0.0; // 蛋白質比例
	double proportion_fat = 0.0;  // 脂肪比例
	double proportion_cho = 0.0;  // 醣類比例
	
	double quantity_Milk = 0.0;  // 牛奶份數
	double quantity_Veg = 0.0;   // 蔬菜份數
	double quantity_Fruit = 0.0; // 水果份數
	double quantity_Grain = 0.0; // 穀類份數
	double quantity_Meat = 0.0;  // 肉類份數
	double quantity_Fat = 0.0;// 油脂份數	
	
	dbBean db = new dbBean() ;

	public boolean isTextNode(Node node){
		return node.getNodeName().equals("#text");
	}	
	
	protected void doPost(HttpServletRequest request,
								HttpServletResponse response )
								throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		
		String user = request.getParameter("user");
		name = (String) request.getSession().getAttribute("login");

		if ((request.isUserInRole("admin") && user.equals("general")) || 
				request.isUserInRole("user") )
		{
			work = request.getParameter( "work" ) ;	
			UserInfo(); // 取得使用者身高體重
			UserCal();	// 計算使用者每日攝取總熱量
			UserNutrients(); // 計算蛋白質、脂肪、醣類克數與比例 			
		}
		else if ((request.isUserInRole("admin") && user.equals("professional")) || 
				request.isUserInRole("professional") )
		{
			activity = request.getParameter("activity");
			pressure = request.getParameter("pressure");
			ProInfo(); // 取得使用者身高、體重、年齡、性別
			ProCal();  // 計算使用者每日攝取總熱量
			
			prot = weight * 1;  //weight * g/kg
			proportion_fat = 0.3;
			ProNutrients(); // 計算蛋白質、脂肪、醣類克數與比例
		}	 
		SixType();     // 計算六大類的份數
		
		System.out.println("calofday:  " + calofday);
		System.out.println("奶: " + quantity_Milk);
		System.out.println("菜: " + quantity_Veg);
		System.out.println("果: " + quantity_Fruit);
		System.out.println("穀: " + quantity_Grain);
		System.out.println("肉: " + quantity_Meat);
		System.out.println("油: " + quantity_Fat);
		
		
		request.getSession().setAttribute("calofday", calofday);
		request.getSession().setAttribute("prot", prot);
		request.getSession().setAttribute("fat", fat);
		request.getSession().setAttribute("cho", cho);
		request.getSession().setAttribute("proportion_prot", proportion_prot) ; 
		request.getSession().setAttribute("proportion_fat", proportion_fat) ;    
		request.getSession().setAttribute("proportion_cho", proportion_cho) ;
		
		request.getSession().setAttribute("quantity_Milk", quantity_Milk) ; 
		request.getSession().setAttribute("quantity_Veg", quantity_Veg) ;    
		request.getSession().setAttribute("quantity_Fruit", quantity_Fruit) ;		
		request.getSession().setAttribute("quantity_Grain", quantity_Grain) ; 
		request.getSession().setAttribute("quantity_Meat", quantity_Meat) ;    
		request.getSession().setAttribute("quantity_Fat", quantity_Fat) ;		
	

		
		//實際份量計算
		
		String[] string = request.getParameterValues("menubox");	
	
		
		// 單日 需要大卡已經取得
		double calofdish = calofday / 3 ;
		// 以下嘗試取得所有食物列表
		ArrayList<String> foodlist = new ArrayList<String>() ;
		ArrayList<String> foodweightlist = new ArrayList<String>() ;
		String path = request.getRealPath("./WEB-INF/menu.xml");
		Document menu = null;
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		try{
			DocumentBuilder builder = factory.newDocumentBuilder();	
			menu = builder.parse(path);	
		}catch(Exception e){
			System.out.print("XML analysis error" + e.getMessage());
		}
		Element body = menu.getDocumentElement();
		NodeList menuList = body.getElementsByTagName("dish"); 
		
		int i = 0, j = 0, k = 0 ;
		while ( i < string.length )
		{
			j = 0 ;
			while ( j < menuList.getLength() )
			{
				Node node = menuList.item(j) ;	
	   		    if ( node.getAttributes().getNamedItem("name").getNodeValue().compareTo(string[i]) == 0 )
				{
					NodeList child = node.getChildNodes();
					k = 0 ;
					while ( k < child.getLength() )
					{
						if ( isTextNode( child.item(k) ) )
						{							
						} // end if
						else
						{
							Node food = child.item(k) ;									
							foodweightlist.add(food.getAttributes().getNamedItem("weight").getNodeValue());
							foodlist.add(food.getFirstChild().getNodeValue());
						} // end else
				
						k++ ;
					} // end while
				} // end if
				j ++ ;
			} // end while
			
			i++ ;
		} // end while
		
		// 取得了所有食物列表跟重量,以下考慮將所有所吃的材料
		// 1. 是否為不建議食物
		// 2. 總熱量約為多少
		// 以下挪用 getFood.java的計算方式 ，得到不適合食物清單
		double calofuserChoose = 0.0; // 使用者選擇總量
	    double calofsugar = 0.0; // 醣類
	    double calofprotein = 0.0; // 蛋白質
	    double caloffat = 0.0; // 肢質

	    double gofMilk = 0.0 ;
	    double gofMilkCho = 0.0 ;
	    double gofMilkFat = 0.0 ;
	    double gofMilkPro = 0.0 ;
	    
	    double gofVeg = 0.0 ;
	    double gofVegCho = 0.0 ;
	    double gofVegFat = 0.0 ;
	    double gofVegPro = 0.0 ;
	    
	    double gofEggBeanFish = 0.0;
	    double gofEggBeanFishFat = 0.0;
	    double gofEggBeanFishCho = 0.0;
	    double gofEggBeanFishPro = 0.0;
	    
	    double gofGrain = 0.0;
	    double gofGrainFat = 0.0;
	    double gofGrainCho = 0.0;
	    double gofGrainPro = 0.0;
	    
	    double gofFruit = 0.0;
	    double gofFruitFat = 0.0;
	    double gofFruitPro = 0.0;
	    double gofFruitCho = 0.0;
	    
	    double gofGrease = 0.0 ;
	    double gofGreaseFat = 0.0 ;
	    double gofGreasePro = 0.0 ;
	    double gofGreaseCho = 0.0 ;
	    
		try {
			String sqlQuery =  "select * from food" ; 			
			ResultSet rs2 = db.ExcuteQuery(sqlQuery) ;	
			while ( rs2.next() ) {						
				 i = 0 ;
				while ( i < foodlist.size() )
				{  
					if ( foodlist.get(i).compareTo(rs2.getString("name")) == 0 )
					{					
						calofuserChoose = calofuserChoose + ( Double.parseDouble(rs2.getString("kcal")) *
								 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight")));
						calofsugar = calofsugar + ( Double.parseDouble(rs2.getString("carbohydrate")) *
								 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight")));
						calofprotein = calofprotein + ( Double.parseDouble(rs2.getString("protein")) *
								 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight")));
						caloffat = caloffat + ( Double.parseDouble(rs2.getString("fat")) *
								 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight")));
						
						//以下計算六大類重量----------------------
						if ( rs2.getString( "type" ).compareTo("奶類") == 0 )
						{
							gofMilk = gofMilk + Double.parseDouble( foodweightlist.get(i) ) ;
							gofMilkCho = ( Double.parseDouble(rs2.getString("carbohydrate")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofMilkPro = ( Double.parseDouble(rs2.getString("protein")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofMilkFat = ( Double.parseDouble(rs2.getString("fat")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
						} // end if
						else if ( rs2.getString("type").compareTo("水果類") == 0 )
						{
							gofFruit = gofFruit + Double.parseDouble( foodweightlist.get(i) ) ;
							gofFruitCho = ( Double.parseDouble(rs2.getString("carbohydrate")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofFruitPro = ( Double.parseDouble(rs2.getString("protein")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofFruitFat = ( Double.parseDouble(rs2.getString("fat")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
						} // end else if
						else if ( rs2.getString("type").compareTo("蔬菜根莖類") == 0 ||
								rs2.getString("type").compareTo("藻類類") == 0 ||
								rs2.getString("type").compareTo("菇類") == 0 )
						{
							gofVeg = gofVeg + Double.parseDouble( foodweightlist.get(i) ) ;
							gofVegCho = ( Double.parseDouble(rs2.getString("carbohydrate")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofVegPro = ( Double.parseDouble(rs2.getString("protein")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofVegFat = ( Double.parseDouble(rs2.getString("fat")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 							
						} // end else if
						else if/* ( rs2.getString("type").compareTo("穀類") == 0 )*/( rs2.getString("type").compareTo("穀物類") == 0 )
						{
							gofGrain = gofGrain + Double.parseDouble( foodweightlist.get(i) ) ;
							gofGrainCho = ( Double.parseDouble(rs2.getString("carbohydrate")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofGrainPro = ( Double.parseDouble(rs2.getString("protein")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofGrainFat = ( Double.parseDouble(rs2.getString("fat")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
						} // end else if
						else if ( rs2.getString("type").compareTo("海鮮類") == 0 ||
								rs2.getString("type").compareTo("肉類") == 0 || 
								rs2.getString("type").compareTo("蛋類") == 0 ||
								rs2.getString("type").compareTo("豆類") == 0 )
						{
							gofEggBeanFish = gofEggBeanFish + Double.parseDouble( foodweightlist.get(i) ) ;
							gofEggBeanFishCho = ( Double.parseDouble(rs2.getString("carbohydrate")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofEggBeanFishPro = ( Double.parseDouble(rs2.getString("protein")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofEggBeanFishFat = ( Double.parseDouble(rs2.getString("fat")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
						} // end else if
						else if ( rs2.getString("type").compareTo("油脂類") == 0 ||
								rs2.getString("type").compareTo("油脂類葷") == 0 ||
								rs2.getString("type").compareTo("堅果種子類") == 0 )
						{
							gofGrease = gofGrease + Double.parseDouble( foodweightlist.get(i) ) ;
							gofGreaseCho = ( Double.parseDouble(rs2.getString("carbohydrate")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofGreasePro = ( Double.parseDouble(rs2.getString("protein")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							gofGreaseFat = ( Double.parseDouble(rs2.getString("fat")) *
									 Double.parseDouble(foodweightlist.get(i)) / Double.parseDouble(rs2.getString("weight"))); 
							
						} // end else if
						
						//----------------------------------
						
					} // end if
					
					i++ ;
				} // end while
				
			} // end while		
		} catch ( Exception e ) {		
			nextpage = ERROR_VIEW ;
		} // end try-catch
		
		
		// = = 
		// calof 還不是卡,而是總重量,以下轉換
		calofsugar = calofsugar * 4 ;
		caloffat = caloffat * 9 ;
		calofprotein = calofprotein * 4 ;
		// = = = = = = =
		// = = = = = = =


	    
	    request.getSession().setAttribute("gofMilk", gofMilk) ; 
	    request.getSession().setAttribute("gofEggBeanFish", gofEggBeanFish) ; 
	    request.getSession().setAttribute("gofGrain", gofGrain) ; 
	    request.getSession().setAttribute("gofFruit", gofFruit) ; 
	    request.getSession().setAttribute("gofVeg", gofVeg) ; 
	    request.getSession().setAttribute("gofGrease", gofGrease) ; 
	    
	    request.getSession().setAttribute("gofFruitPro", gofFruitPro) ;
	    request.getSession().setAttribute("gofFruitFat", gofFruitFat) ;
	    request.getSession().setAttribute("gofFruitCho", gofFruitCho) ;
	    request.getSession().setAttribute("gofMilkPro", gofMilkPro) ;
	    request.getSession().setAttribute("gofMilkFat", gofMilkFat) ;
	    request.getSession().setAttribute("gofMilkCho", gofMilkCho) ;
	    request.getSession().setAttribute("gofEggBeanFishPro", gofEggBeanFishPro) ;
	    request.getSession().setAttribute("gofEggBeanFishFat", gofEggBeanFishFat) ;
	    request.getSession().setAttribute("gofEggBeanFishCho", gofEggBeanFishCho) ;
	    request.getSession().setAttribute("gofGrainPro", gofGrainPro) ;
	    request.getSession().setAttribute("gofGrainFat", gofGrainFat) ;
	    request.getSession().setAttribute("gofGrainCho", gofGrainCho) ;
	    request.getSession().setAttribute("gofVegPro", gofVegPro) ;
	    request.getSession().setAttribute("gofVegFat", gofVegFat) ;
	    request.getSession().setAttribute("gofVegCho", gofVegCho) ;
	    request.getSession().setAttribute("gofGreasePro", gofGreasePro) ;
	    request.getSession().setAttribute("gofGreaseFat", gofGreaseFat) ;
	    request.getSession().setAttribute("gofGreaseCho", gofGreaseCho) ;
	    
		request.getSession().setAttribute("calofsugar", calofsugar) ; 
		request.getSession().setAttribute("caloffat", caloffat) ;    
		request.getSession().setAttribute("calofprotein", calofprotein) ;		
		request.getSession().setAttribute("calofdish_userChoose", calofuserChoose) ;
		request.getSession().setAttribute("calofday", calofday);
		request.getSession().setAttribute("foodweightlist", foodweightlist);
		request.getSession().setAttribute("foodlist", foodlist);
		
		
		request.getRequestDispatcher(nextpage).forward(request, response);
	
	} // end doGet()

	private void SixType() {
		// TODO Auto-generated method stub
		if (calofday >= 2000) // 2000大卡以上奶類2份
			quantity_Milk = 2;
		else
			quantity_Milk = 1.5;
		
		
		if (sex.equals("male"))  // 男生蔬菜5份、水果4份
		{
			quantity_Veg = 5;
			quantity_Fruit = 4;
		}
		else  // female 女生蔬菜4份、水果3份
		{
			quantity_Veg = 4;
			quantity_Fruit = 3;
		}
		
		// 低脂奶類: prot 每份8g、fat每份4g、cho每份12g
		// 蔬菜:    prot 每份1g、fat每份0g、cho每份5g 
		// 水果:    prot 每份0g、fat每份0g、cho每份15g
		// 穀類:    prot 每份2g、fat每份0g、cho每份15g
	    // 豆魚肉蛋: prot 每份7g、fat每份5g、cho每份0g
	    // 油脂:    prot 每份0g、fat每份5g、cho每份0g
		
		quantity_Grain = (cho - quantity_Milk * 12 - quantity_Veg * 5 -
				          quantity_Fruit * 15) / 15; 
		quantity_Grain = Adjust_quantity(quantity_Grain);
		quantity_Meat = ( prot - quantity_Milk * 8 - quantity_Veg -
				          quantity_Grain * 2 ) / 7;
		quantity_Meat = Adjust_quantity(quantity_Meat);
		quantity_Fat = (fat - quantity_Milk * 4 - quantity_Meat * 5) / 5;
		quantity_Fat = Adjust_quantity(quantity_Fat);
	}

	private double Adjust_quantity(double quantity) {
		// TODO Auto-generated method stub
		DecimalFormat df = new DecimalFormat("#.#");
		quantity = Double.parseDouble(df.format(quantity));
		double decimal = quantity - (int)quantity;
		if (decimal <= 0.2)
			return (int)quantity;
		else if (decimal >= 0.8)
			return (int)(quantity+1);
		else
			return ((int)quantity)+0.5;
	}

	private void ProNutrients() {
		// TODO Auto-generated method stub
		proportion_prot = prot * 4 / calofday;
		fat = calofday * proportion_fat / 9;
		proportion_cho = 1 - proportion_fat - proportion_prot;
		cho = calofday * proportion_cho / 4;	
		
		proportion_prot = proportion_prot * 100; // 蛋白質百分比
		proportion_fat = proportion_fat * 100;  // 脂肪百分比
		proportion_cho = proportion_cho * 100;  // 醣類百分比
	}

	private void UserNutrients() {
		// TODO Auto-generated method stub
		
		prot = weight;  // 蛋白質 1 g/kg
		proportion_prot = prot * 4 / calofday;
		fat = calofday * 0.3 / 9;
		proportion_cho = 1 - 0.3 - proportion_prot;
		cho = calofday * proportion_cho / 4;	
		
		proportion_prot = proportion_prot * 100; // 蛋白質百分比
		proportion_fat = 30;  // 脂肪百分比
		proportion_cho = proportion_cho * 100;  // 醣類百分比
	}

	private void ProCal() {
		// TODO Auto-generated method stub
		double bee = 0.0;
		double pressureInt = Double.parseDouble(pressure);
		
		if (sex.equals("male"))  // 男性 BEE = 66+13.7x體重 + 5 x身高-6.8 x年齡
			bee = 66 + 13.7 * weight + 5 * height - 6.8 * year;			
		else  // female  女性 BEE = 655+9.6x體重+1.8x身高- 4.7 x年齡
			bee = 655 + 9.6 * weight + 1.8 * height - 4.7 * year;

		if ( activity.equals("little") )
			calofday = bee * 1.2 * pressureInt; 
		else if ( activity.equals("middle") )
			calofday = bee * 1.3 * pressureInt ;
		else if ( activity.equals("large") )
			calofday = bee * 1.4 * pressureInt ;	
	}

	private void UserCal() {
		// TODO Auto-generated method stub
		double bmi = weight / ( height / 100 * height / 100 ) ;		
		if ( bmi < 18.5 ) // 過輕
		{
			if ( work.compareTo("little") == 0 )
				calofday = 35 * weight ; 
			else if ( work.compareTo("middle") == 0 )
				calofday = 40 * weight ;
			else
				calofday = 45 * weight ;
		} // end if
		else if ( bmi <=24 ) // 正常
		{
			if ( work.compareTo("little") == 0 )
				calofday = 30 * weight ; 
			else if ( work.compareTo("middle") == 0 )
				calofday = 35 * weight ;
			else
				calofday = 40 * weight ;
		} // end else if
		else if ( bmi <=27 ) // 過重
		{
			if ( work.compareTo("little") == 0 )
				calofday = 25 * weight ; 
			else if ( work.compareTo("middle") == 0 )
				calofday = 30 * weight ;
			else
				calofday = 35 * weight ;
		} // end else if
		else if ( bmi <=30 ) // 一度肥胖
		{
			if ( work.compareTo("little") == 0 )
				calofday = 20 * weight ; 
			else if ( work.compareTo("middle") == 0 )
				calofday = 30 * weight ;
			else if ( work.compareTo("large") == 0 )
				calofday = 35 * weight ;
		} // end else if
		else if ( bmi <=35 ) // 二度肥胖
		{
			if ( work.compareTo("little") == 0 )
				calofday = 20 * weight ; 
			else if ( work.compareTo("middle") == 0 )
				calofday = 30 * weight ;
			else
				calofday = 35 * weight ;
		} // end else if
		else // 三度肥旁(病態肥胖) BMI > 35
		{
			if ( work.compareTo("little") == 0 )
				calofday = 20 * weight ; 
			else if ( work.compareTo("middle") == 0 )
				calofday = 30 * weight ;
			else
				calofday = 35 * weight ;
		} // end else
	}

	private void UserInfo() {
		// TODO Auto-generated method stub
		
		db.setDataSource("jdbc/ctmpllab");
		db.Connected();	
		
		try {
			ResultSet rs = db.ExcuteQuery("select weight, height, sex from accounttable " +
										  "where account='"	+ name + "'") ;
			rs.next();
			weight = Double.parseDouble(rs.getString("weight")) ;
			height = Double.parseDouble(rs.getString("height")) ;
			sex = rs.getString("sex");
		} catch (SQLException e) {			
			nextpage = ERROR_VIEW ;
			e.printStackTrace();
		} // end try-catch
	}

	private void ProInfo() {
		// TODO Auto-generated method stub
		dbBean db = new dbBean() ;
		db.setDataSource("jdbc/ctmpllab");
		db.Connected();	
		
		try {
			ResultSet rs = db.ExcuteQuery("select weight, height, year, sex from accounttable " +
										  "where account='"	+ name + "'") ;
			rs.next();
			weight = Double.parseDouble(rs.getString("weight")) ;
			height = Double.parseDouble(rs.getString("height")) ;
			Date MyDate = new Date(); // 宣告系統日期之日期變數... 			
			SimpleDateFormat sdfSource = new SimpleDateFormat("yyyy");
			String DateStr = sdfSource.format(MyDate); //year轉字串
			year = Double.parseDouble(DateStr) - Double.parseDouble(rs.getString("year")) ;
			sex = rs.getString("sex");
		} catch (SQLException e) {
			nextpage = ERROR_VIEW ;
			e.printStackTrace();
		} // end try-catch
	
	}

}
